import cv2
from pathlib import Path
import numpy as np

basedir= r"F:\bigphoto\imagu\card"
import os
images = [os.path.join(basedir,i) for i in os.listdir(basedir)]

def show(img,name):
    cv2.imshow(name,img)
    cv2.waitKey(15000)
    cv2.destroyAllWindows()

def _binary(im):
    max = np.max(im)
    min = np.min(im)
    mean = (max-min)//2
    _,im = cv2.threshold(im,mean,255,cv2.THRESH_BINARY)
    return im


def stretch(img):
    max = float(img.max())
    min = float(img.min())

    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            img[i, j] = (255 / (max - min)) * img[i, j] - (255 * min) / (max - min)

    return img

def morgrad(im):
    erding = cv2.erode(im,cv2.getStructuringElement(cv2.MORPH_RECT,(3,3)))
    diaing = cv2.dilate(im,cv2.getStructuringElement(cv2.MORPH_RECT,(3,3)))
    res = cv2.subtract(erding,diaing)
    cv2.imshow("grad",erding)
    return res

def find_lincese(im):
    contours, hierarchy = cv2.findContours(im,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    final_ct = []
    for contour in contours:
        area =cv2.contourArea(contour)
        if area < 60:
            continue
        x,y,w,h = cv2.boundingRect(contour)
        if w/h < 2 or w/h > 6:
            continue
        final_ct.append(contour)
    return final_ct

def single(imgname):
    imo = cv2.imread(imgname)
    img = cv2.cvtColor(imo,cv2.COLOR_BGR2GRAY)
    im = stretch(img)
    cv2.imshow("gray",im)

    # im = morgrad(im)
    # cv2.imshow("equal",im)

    r = 17
    h=w=r * 2 + 1
    kernel = np.zeros((h,w),dtype=np.uint8)
    cv2.circle(kernel,(r,r),r,1,-1)
    openingimg = cv2.morphologyEx(im,cv2.MORPH_OPEN,kernel,iterations=1)
    strtimg = cv2.absdiff(im,openingimg) # 顶帽 突出原图中小区域周围比较亮的图

    cv2.imshow("top hat ",strtimg)
    # openingimg = cv2.morphologyEx(strtimg, cv2.MORPH_OPEN, kernel, iterations=1)
    # strtimg = cv2.absdiff(strtimg, openingimg)  # 顶帽 突出原图中小区域周围比较亮的图
    strtimg = cv2.GaussianBlur(strtimg,(9,3),0,0)
    strtimg = cv2.Sobel(strtimg,cv2.CV_8U,1,0,3)
    cv2.imshow('Sobel',strtimg)
    im = _binary(strtimg)
    cv2.imshow('bina',im)
    # im = cv2.adaptiveThreshold(strtimg,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,15,3)


    # dx = cv2.Sobel(im,cv2.CV_16S,1,0)
    # dy = cv2.Sobel(im,cv2.CV_16S,0,1)
    # absX = cv2.convertScaleAbs(dx)
    # absY = cv2.convertScaleAbs(dy)
    # im = cv2.addWeighted(absX,0.8,absY,0.2,0)

    # cannyimg = cv2.Canny(im,im.shape[0],im.shape[1])

    '''
    消除小区域，连通大区域
    '''
    kernel = np.ones((5, 19), np.uint8)
    closingimg = cv2.morphologyEx(im, cv2.MORPH_CLOSE, kernel,iterations=2)
    #
    # # 进行开运算
    kernel = np.ones((5,5),np.uint8)
    openingimg = cv2.morphologyEx(closingimg, cv2.MORPH_OPEN, kernel)
    #
    # # 再次进行开运算
    kernel = np.ones((11, 5), np.uint8)
    openingimg = cv2.morphologyEx(openingimg, cv2.MORPH_OPEN, kernel)

    contours = find_lincese(openingimg)
    print(len(contours))
    for contour in contours:
        x,y,w,h = cv2.boundingRect(contour)
        cv2.rectangle(imo,(x,y),(x + w, y + h),(0,0,255),3)
    # cv2.imshow('openingimg', openingimg)
    # cv2.waitKey()

    # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 1))
    # im = cv2.dilate(im, kernel)

    # _,im = cv2.threshold(img,_convert2gray(img),255,cv2.THRESH_BINARY)
    # kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
    # im = cv2.GaussianBlur(im,(5,5),0.4)
    # im = cv2.medianBlur(im,3)
    # ele = cv2.getStructuringElement(cv2.MORPH_RECT,(10,1))
    # im = cv2.erode(im,cv2.getStructuringElement(cv2.MORPH_RECT,(3,3)))
    # im = cv2.dilate(im,cv2.getStructuringElement(cv2.MORPH_RECT,(3,3)))

    # 利用sobel算子加强图片
    # dx = cv2.Sobel(im,cv2.CV_16S,1,0)
    # dy = cv2.Sobel(im,cv2.CV_16S,0,1)
    # print(f'dx',dx.shape)
    # absX = cv2.convertScaleAbs(dx)
    # absY = cv2.convertScaleAbs(dy)
    # im = cv2.addWeighted(absX,0.5,absY,0.5,0)
    # im = cv2.dilate(im,ele,iterations=3)
    # im = cv2.dilate(im,ele)
    # im = cv2.dilate(im,ele)
    #
    # # ele2  = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
    #
    # _,contours,_ = cv2.findContours(im,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
    # for contour in contours:
    #     if cv2.contourArea(contour) < 30:
    #         continue
    #     # print(cv2.contourArea(contour))
    #     # input("")
    #     x1,y1,x2,y2= cv2.boundingRect(contour)
    #     cv2.rectangle(imo,(x1,y1),(x2,y2),(0,255,0),1)
        # cv2.imshow('sfs',imo)
        # cv2.waitKey(5000)
    # print(im)
    show(imo,imgname)

single(images[0])
# https://blog.csdn.net/u013488619/article/details/73277507
# https://blog.csdn.net/jiaoyangwm/article/details/81088578
# https://my.oschina.net/airxiechao/blog/2239875